/*
 * response_panel.c
 * This file is part of gURL
 *
 * Copyright (C) 2013, 2014 - Aleksey Konovalov
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Library General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "response_panel.h"

#include <assert.h>
#include "defines.h"
#include <glib/gi18n.h>
#include "gurl_conf.h"
#include "highlighter/highlighter.h"
#include "response_body_view.h"
#include <stdbool.h>
#include "text_edit.h"
#include "utils.h"

#ifdef HAVE_CONFIG_H
#   include <config.h>
#endif

struct _ResponsePanel {
    GtkNotebook parent;
    GtkWidget* summary;
    GtkWidget* headers;
    GtkWidget* body_viewer;

    gulong session_upd_signal_handle;
    Session* session;
};

struct _ResponsePanelClass {
    GtkNotebookClass parent_class;
};

enum {
    PAGE_SUMMARY,
    PAGE_HEADERS,
    PAGE_BODY,
};

G_DEFINE_TYPE(ResponsePanel, response_panel, GTK_TYPE_NOTEBOOK)

static const char* const CONF_GROUP = "response view";
static const char* const CONF_PRETTYPRINT_KEY = "prettyprint";

void response_panel_set_session(ResponsePanel* rp, Session* session);

static void refresh(ResponsePanel* rp) {
    if(rp->session)
        response_panel_set_session(rp, rp->session);
}

static void update_summary(ResponsePanel* rp) {
    GtkTextBuffer* tb = gtk_text_view_get_buffer(
                            GTK_TEXT_VIEW(rp->summary));
    const Session* s = rp->session;
    if(s) {
        GString* info = g_string_sized_new(1024);
        g_string_printf(info, _("Response status: %ld\n"
                                "Total time: %lf s\n"
                                "Name lookup time: %lf s\n"
                                "Connect time: %lf s\n"
                                "Pretransfer time: %lf s\n"
                                "Error: %s"),
                        s->response.status,
                        s->statistics.total_time,
                        s->statistics.namelookup_time,
                        s->statistics.connect_time,
                        s->statistics.pretransfer_time,
                        s->statistics.str_error);
        gtk_text_buffer_set_text(tb, info->str, info->len);
        g_string_free(info, TRUE);
    } else
      gtk_text_buffer_set_text(tb, "", 0);
}

static void update_headers(ResponsePanel* rp) {
    GtkTextBuffer* tb = gtk_text_view_get_buffer(
                            GTK_TEXT_VIEW(rp->headers));
    if(rp->session) {
        const GString* hdrs = session_get_response_headers(rp->session);
        gchar* hdrs_converted = g_convert_with_fallback(
            hdrs->str, hdrs->len, "ASCII", "ISO-8859-1", "?", NULL, NULL, NULL);
        gtk_text_buffer_set_text(tb, hdrs_converted, hdrs->len);
        highlight_http_headers(tb, hdrs_converted, hdrs->len);
        g_free(hdrs_converted);
    } else
        gtk_text_buffer_set_text(tb, "", 0);
}

static void update_body(ResponsePanel* rp) {
    response_body_view_change_session(RESPONSE_BODY_VIEW(rp->body_viewer),
                                      rp->session);
}

static void refresh_notepad_page(ResponsePanel* rp, gint page_num) {
    switch(page_num) {
        case PAGE_SUMMARY: update_summary(rp); break;
        case PAGE_HEADERS: update_headers(rp); break;
        case PAGE_BODY:    update_body(rp); break;
        default: assert(0);
    }
}

static void on_notepad_switch(GtkNotebook* notebook, GtkWidget* UNUSED(page),
                              guint page_num, gpointer UNUSED(user_data)) {
    refresh_notepad_page(RESPONSE_PANEL(notebook), page_num);
}

static void response_panel_init(ResponsePanel* self) {
    self->session = NULL;

    g_signal_connect(GTK_NOTEBOOK(self), "switch-page",
                     G_CALLBACK(on_notepad_switch), NULL);

    self->summary = gtk_text_view_new();
    gtk_widget_show(self->summary);
    gtk_text_view_set_editable(GTK_TEXT_VIEW(self->summary), false);
    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(self->summary), false);
    GtkWidget* sw = add_to_scrolled_window(self->summary);
    g_object_set(G_OBJECT(sw), "margin", 7, NULL);
    gtk_notebook_append_page(GTK_NOTEBOOK(self), sw,
                             gtk_label_new(_("Summary")));

    self->headers = gtk_text_view_new();
    gtk_widget_show(self->headers);
    gtk_text_view_set_editable(GTK_TEXT_VIEW(self->headers), false);
    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(self->headers), false);
    sw = add_to_scrolled_window(self->headers);
    g_object_set(G_OBJECT(sw), "margin", 7, NULL);
    gtk_notebook_append_page(GTK_NOTEBOOK(self), sw,
                             gtk_label_new(_("Headers")));

    self->body_viewer = response_body_view_new();
    gtk_widget_show(self->body_viewer);
    gtk_notebook_append_page(GTK_NOTEBOOK(self), self->body_viewer,
                             gtk_label_new(_("Body")));

/*#ifdef HAVE_GHEX
    self->body_hex_doc = hex_document_new();
    GtkWidget* body_hex = gtk_hex_new(self->body_hex_doc);
    gtk_widget_show(body_hex);
    self->body_hex_doc->views =
        g_list_append(self->body_hex_doc->views, body_hex);
    gtk_widget_set_has_window(body_hex, true);
    gtk_notebook_append_page(GTK_NOTEBOOK(self), body_hex,
                             gtk_label_new(_("Body [HEX]")));
    self->body_hex_doc_len = 0;
#endif

#ifdef HAVE_GTKHTML
    self->body_html = gtk_html_new();
    gtk_widget_show(self->body_html);
    gtk_notebook_append_page(GTK_NOTEBOOK(self),
                             add_to_scrolled_window(self->body_html),
                             gtk_label_new(_("Body [Web view]")));
#endif

#ifdef HAVE_JSON_GLIB
    self->body_json = json_viewer_new();
    gtk_widget_show(self->body_json);
    gtk_notebook_append_page(GTK_NOTEBOOK(self),
                             add_to_scrolled_window(self->body_json),
                             gtk_label_new(_("Body [JSON view]")));
#endif*/
}

static void response_panel_dispose(GObject* object) {
    ResponsePanel* rp = RESPONSE_PANEL(object);
    if(rp->session) {
        g_object_unref(rp->session);
        rp->session = NULL;
    }
}

void response_panel_class_init(ResponsePanelClass* klass) {
    G_OBJECT_CLASS(klass)->dispose = response_panel_dispose;
}

static void update_session_cb(Session* UNUSED(session), updated_information upd,
                              ResponsePanel* rp) {
    int current_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(rp));
    bool need_update = false;
    switch(current_page) {
        case PAGE_HEADERS: need_update = upd == uRESPONSE_HEADERS; break;
        case PAGE_BODY:    need_update = upd == uRESPONSE_BODY; break;
    };
    if(need_update)
        refresh_notepad_page(rp, current_page);
}

void response_panel_set_session(ResponsePanel* rp, Session* session) {
    if(rp->session)
        g_object_unref(rp->session);
    if(rp->session)
        g_signal_handler_disconnect(rp->session, rp->session_upd_signal_handle);
    rp->session = session;
    if(session) {
        g_object_ref(session);
        rp->session_upd_signal_handle =
            g_signal_connect(session, "update", G_CALLBACK(update_session_cb), rp);
    }
    refresh_notepad_page(rp, gtk_notebook_get_current_page(GTK_NOTEBOOK(rp)));
}

GtkWidget* response_panel_new() {
    return g_object_new(RESPONSE_PANEL_TYPE, NULL);
}
